// pages/blechat/blechat.js

// 引入文本编码器和解码器工具
import TextEncoder from '../../utils/miniprogram-text-encoder';
import TextDecoder from '../../utils/miniprogram-text-decoder';

// 测试用的UTF-8字符串
const utf8String = "H 王博士"

// android的手机测试是大写，而黑苹果是小写 .toUpperCase()
const SERVICE_UUID = "2D5BAA90-35A1-4345-88BC-B8F84E0FCC63";
const META_CHAR_UUID = "2D5BAA91-35A1-4345-88BC-B8F84E0FCC63";
const DATA_CHAR_UUID = "2D5BAA92-35A1-4345-88BC-B8F84E0FCC63";

const PAGE_SIZE = 20; // 分包大小(字节)

// 在数组中查找指定键值对的索引
function inArray(arr, key, val) {
  for (let i = 0; i < arr.length; i++) {
    if (arr[i][key] === val) {
      return i;
    }
  }
  return -1;
}

// 16进制字符串转ArrayBuffer
function hexStringToArrayBuffer(hexString) {
  let byteArray = new Uint8Array(hexString.length / 2);

  for (let i = 0; i < hexString.length; i += 2) {
    byteArray[i / 2] = parseInt(hexString.substr(i, 2), 16);
  }

  return byteArray.buffer;
}

// 同步延时函数
function sleep(delay) {
  let start = (new Date()).getTime();
  while ((new Date()).getTime() - start < delay) {
    continue;
  }
}
// ArrayBuffer转16进度字符串示例
function ab2hex(buffer) {
  if (!buffer || buffer.length <= 0) {
    return ''
  }
  let hexArr = Array.prototype.map.call(
    new Uint8Array(buffer),
    function (bit) {
      return ('00' + bit.toString(16)).slice(-2)
    }
  )
  return hexArr.join('');
}

Page({
  data: {

    isShowBack: true,
    isShowHome: true,
    titleColor: '#ffffff',
    background: 'linear-gradient(135deg, #ff705d 0%, #d81e06 100%)',
    title: '蓝牙通信内容',

    // disconnecByWill:false, // 主动断开              
    deviceId: '', // 蓝牙设备ID
    deviceName: '', // 蓝牙设备名称
    serviceId: '', // 服务UUID
    logInfo: [], // 日志信息

    meta_chunks_number: -1,
    data_chunks_hex_string: "", // data接收的数据变成hex string

    connected: false, // 连接状态

    // pageSize: 20, // 分包大小(字节)
    listening: false, // 是否正在监听
    connectStateListening: false, // 是否正在监听连接状态

    messages: [
      { id: 1, type: 'other', content: '从蓝牙读取消息。', avatar: 'https://picsum.photos/200/200?random=1' },
    ],
    inputValue: '',
    scrollTop: 0,
    defaultAvatar: 'https://picsum.photos/200/200?random=1',
    userAvatar: 'https://picsum.photos/200/200?random=2'
  },

  onLoad(options) {

    console.log('param name:', options.name)
    this.setData({
      deviceId: options.deviceId,
      deviceName: options.name,
    });


    // 页面加载时滚动到底部
    this.setData({
      scrollTop: 9999
    });
  },

  // 输入框内容变化
  onInput(e) {
    this.setData({
      inputValue: e.detail.value
    });
  },

  // 输入框聚焦
  onFocus() {
    // 输入框聚焦时滚动到底部
    this.setData({
      scrollTop: 9999
    });
  },

  // 输入框失焦
  onBlur() {
    // 可以在这里处理一些失焦逻辑
  },

  // 发送消息
  sendMessage() {
    const content = this.data.inputValue.trim();
    if (!content) return;

    // 添加新消息
    const newMessage = {
      id: Date.now(),
      type: 'self',
      content: content
    };

    this.setData({
      messages: [...this.data.messages, newMessage],
      inputValue: '',
      scrollTop: 9999
    });

    // 模拟回复
    this.simulateReply(content);
  },

  // 模拟回复
  simulateReply(content) {
    setTimeout(() => {
      const replies = [
        '明白了，还有其他需求吗？',
        '好的，我会处理的。',
        '收到，谢谢告知！',
        '非常感谢您的反馈！',
        '这是个很好的建议。'
      ];
      
      const randomIndex = Math.floor(Math.random() * replies.length);
      const replyMessage = {
        id: Date.now(),
        type: 'other',
        content: replies[randomIndex],
        avatar: this.data.defaultAvatar
      };

      this.setData({
        messages: [...this.data.messages, replyMessage],
        scrollTop: 9999
      });
    }, 1000);
  },

  // 加载更多历史消息
  loadMoreMessages() {
    // 这里可以实现加载历史消息的逻辑
    console.log('加载更多历史消息');
  },

  ////////////////////////////////////
 // 连接蓝牙设备
  connectDevice() {
    this.createBLEConnection();
  },

  // 关闭连接
  closeConnection() {
    this.output('closeConnection...')
    this.removeRecvListener();
    this.closeBLEConnection();
  },

  // 创建蓝牙连接
  createBLEConnection(e) {
    console.log('createBLEConnection...')
    // debugger
    let that = this;
    const deviceId = this.data.deviceId
    const name = this.data.deviceName
    console.log(`createBLEConnection name:${name}`)
    wx.createBLEConnection({
      deviceId,
      success: (res) => {
        console.log('建立与设备的蓝牙连接成功。。。deviceId:', deviceId)
        this.output(`连接成功 ${deviceId}`)
        console.log('查询services')
        this.getBLEDeviceServices(deviceId)
      },
      fail: (err) => {
        console.log('建立与设备的蓝牙连接 失败:', err)
        this.output(`建立与设备的蓝牙连接 失败:${err}`)
      }
    })
    this.stopBluetoothDevicesDiscovery()
  },

  // 关闭蓝牙连接
  closeBLEConnection() {
    console.log('closeBLEConnection...')
    wx.closeBLEConnection({
      deviceId: this.data.deviceId
    })
    this.setData({
      // connected: false,

      // canWrite: false,
    })
  },

  // 非阻塞sleep
  sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  },
  // 王博士写的两个方法：

  // Example usage
  // const uuid = generateUUID();
  // console.log(uuid);
  generateUUID: function () {
    return 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
      let r = Math.random() * 16 | 0,
        v = c == 'x' ? r : (r & 0x3 | 0x8);
      return v.toString(16);
    });
  },

  hexToUtf8: function (hexString) {
    // 移除十六进制字符串中的空格（如果存在）
    hexString = hexString.replace(/\s+/g, '');

    // 将十六进制字符串转换为 Uint8Array
    const bytes = new Uint8Array(hexString.length / 2);
    for (let i = 0; i < hexString.length; i += 2) {
      bytes[i / 2] = parseInt(hexString.substr(i, 2), 16);
    }

    // 使用 TextDecoder 将字节数组解码为 UTF-8 字符串
    const decoder = new TextDecoder('utf-8');
    return decoder.decode(bytes);
  },

  // 接收消息
  // 1. 准备数据：自己的姓名，制作成json，变成hex
  // 2. 连接truetalk
  // 3. 给meta char 发送消息长度，给meta的消息为二进制。等待meta给出OK提示，等待200毫秒
  // 4. 给data char 循环发送hex，等待data给出OK提示，等待200毫秒
  // 5. 接收meta char的二进制信息。解码成功后，保存数据到this.data，给meta以OK提示，等待200毫秒
  // 6. 循环接收data信息。解码。给出OK提示
  // 7. 断开truetalk
  async truetalkReadMessage() {

    // 1. 准备数据：自己的姓名，制作成json，变成hex
    const myUuid = "wangshaoning_gdsrghdshsthshs"; // this.generateUUID();
    const myUuidJson = {
      "cmd": "recv",
      "id": myUuid
    }
    const utf8String = JSON.stringify(myUuidJson, null);
    const encoder = new TextEncoder();
    const encodedData = encoder.encode(utf8String);
    console.log('写入数据 data len:', encodedData.byteLength);
    console.log('写入数据 data:', encodedData);


    // 2. 连接truetalk
    console.log('createBLEConnection...')
    let createBLEConnectionPromise = await this.createBLEConnectionPromise()
    let that = this;

    wx.notifyBLECharacteristicValueChange({
      characteristicId: DATA_CHAR_UUID,
      state: true, // 启用 notify 功能
      deviceId: this.data.deviceId,
      type: "notification",
      serviceId: SERVICE_UUID,
      success: (res) => {
        console.log(res, "notify创建连接，发送指令")

      },
      fail: (res) => {
        // ios有可能取消匹配，也会调用这里
      },
      complete: (res) => {
        console.log("notifyed")
      }
    })

    wx.notifyBLECharacteristicValueChange({
      characteristicId: META_CHAR_UUID,
      state: true, // 启用 notify 功能
      deviceId: this.data.deviceId,
      type: "notification",
      serviceId: SERVICE_UUID,
      success: (res) => {
        console.log(res, "notify创建连接，发送指令")

      },
      fail: (res) => {
        // ios有可能取消匹配，也会调用这里
      },
      complete: (res) => {
        console.log("notifyed")
      }
    })

    wx.onBLECharacteristicValueChange(function (res) {
      console.log(`characteristic ${res.characteristicId} has changed, now is ${res.value}`)
      console.log(ab2hex(res.value))

      if(res.characteristicId == META_CHAR_UUID)
      {
        that.handleRecvData_meta(res.value)
      }
      else{
        that.handleRecvData_data(res.value)
      }
      

      // that.setRecvListener_new(that.data.deviceId, SERVICE_UUID, res.characteristicId);
      //this.setRecvListener_new(this.data.deviceId, SERVICE_UUID, DATA_CHAR_UUID);
    })




    // 3. 给meta char 发送消息长度，给meta的消息为二进制。等待meta给出OK提示，等待200毫秒

    //this.stopBluetoothDevicesDiscovery()


    // let dataBuffer = hexStringToArrayBuffer("4820e78e8be58d9ae5a3ab");
    const pages_count = Math.ceil(encodedData.byteLength / PAGE_SIZE);

    const metaLengthUint8 = encoder.encode(pages_count.toString());
    console.log("metaLengthUint8.byteLength = ", metaLengthUint8.byteLength)


    // 4. 给data char 循环发送hex，等待data给出OK提示，等待200毫秒
    // 5. 接收meta char的二进制信息。解码成功后，保存数据到this.data，给meta以OK提示，等待200毫秒
    // 6. 循环接收data信息。解码。给出OK提示
    // 7. 断开truetalk

    this.writeDataByPage(metaLengthUint8.buffer, this.data.deviceId, SERVICE_UUID, META_CHAR_UUID)
    sleep(20)
    this.writeDataByPage(encodedData.buffer, this.data.deviceId, SERVICE_UUID, DATA_CHAR_UUID)

    // 给服务器留足时间。我方服务器收到消息后，会主动断开连接。


  },

  // 1. 连接truetalk
  // 2. 准备数据：自己的姓名，制作成json，变成hex
  // 3. 给meta char 发送消息长度，给meta的消息为二进制。等待meta给出OK提示，等待200毫秒
  // 4. 给data char 循环发送hex，等待data给出OK提示，等待200毫秒
  // 5. 断开truetalk
  // 6. 

  truetalkWriteMessage() {

  },


  // promise的蓝牙连接
  createBLEConnectionPromise() {

    return new Promise((resolve, reject) => {
      const deviceId = this.data.deviceId;
      console.log("promise's deviceId =", deviceId)
      wx.createBLEConnection({
        deviceId,
        success: (res) => {
          console.log('建立与设备的蓝牙连接成功。。。deviceId:', deviceId)
          this.output(`连接成功 ${deviceId}`)
          resolve(res)
        },
        fail: (err) => {
          console.log('建立与设备的蓝牙连接 失败:', err)
          this.output(`建立与设备的蓝牙连接 失败:${err}`)
          reject(err)
        }
      })
    })
  },

  // 不分块写入的方法
  writeBLECharacteristicValuePromise(buffer, deviceId, serviceId, characteristicId) {
    return new Promise((resolve, reject) => {
      wx.writeBLECharacteristicValue({
        deviceId: deviceId,
        serviceId: serviceId,
        characteristicId: characteristicId,
        value: buffer,
        success: (res) => {
          console.log('发送数据成功:', res)
          this.output('发送数据成功')
          // this.readBleData();
        },
        fail: (err) => {
          console.log('发送数据失败:', err)
          this.output('发送数据失败')
        }
      })
    })
  },



  // wang 写的新的版本。
  handleRecvData_meta(value) {
    console.log('-------meta recv Data:', ab2hex(value));

    let china_str = new TextDecoder().decode(value)
    console.log(china_str)
    const meta_chunks_number = parseInt(china_str);
    this.setData({
      meta_chunks_number: meta_chunks_number
    })
    this.output(`recv ${ab2hex(value)}`)
  },

  // wang 写的新的版本。
  handleRecvData_data(value) {
    console.log('-------recv Data:', ab2hex(value));
    console.log('-------recv Data，meta_chunks_number :', this.data.meta_chunks_number);
    let current_data_chunks_hex_string = this.data.data_chunks_hex_string + ab2hex(value)

    this.setData({
      data_chunks_hex_string: current_data_chunks_hex_string
    })

    if (this.data.meta_chunks_number > 1) {
      this.setData({
        meta_chunks_number: this.data.meta_chunks_number - 1
      })
    } else {
      // 最后一次
      const string_china_total = this.hexToUtf8(this.data.data_chunks_hex_string);
      console.log("string_china_total = ", string_china_total)
      // 做完以后，把所有的数据清零
      this.setData({
        data_chunks_hex_string: ""
      })
      
      let objJson = {"text": "没有收到消息"}
      try {
        objJson = JSON.parse(string_china_total);
        console.log(objJson.text); // 输出: 张三
      } catch (error) {
        console.error('JSON 解析错误:', error);
      }

      // 根据 objJson 操作

      const replyMessage = {
        id: Date.now(),
        type: 'other',
        content: objJson.text,
        avatar: this.data.defaultAvatar
      };

      this.setData({
        messages: [...this.data.messages, replyMessage],
        scrollTop: 9999
      });

      // 最后关闭
      this.closeConnection();

    } // end of if (this.data.meta_chunks_number > 1) // else {


  },


  // 我改写的内容。分包写入数据
  writeDataByPage(buffer, deviceId, serviceId, characteristicId) {
    let pos = 0;
    let bytesLength = buffer.byteLength;
    var that = this;
    let arrayBuffer = buffer;
    console.log("bytes", bytesLength)
    console.log("arrayBuffer", buffer)
    console.log("arrayBuffer", arrayBuffer)
    while (bytesLength > 0) {
      let tmpBuffer;
      if (bytesLength > PAGE_SIZE) {
        tmpBuffer = arrayBuffer.slice(pos, pos + PAGE_SIZE);
        pos += PAGE_SIZE;
        bytesLength -= PAGE_SIZE;
        that.writeBLEDataCommon(tmpBuffer, deviceId, serviceId, characteristicId,
          function (res) {
            that.output(`常规包发送成功 ${tmpBuffer}`)
          },
          function (res) {
            if (res.errCode == '10006') {
              that.clearConnectData(); //当前连接已断开，清空连接数据
              that.output('当前连接已断开');
            }
            that.output(`>pageSize 发送失败 ${res.errCode }`)
          })
        sleep(0.02)
      } else {
        tmpBuffer = arrayBuffer.slice(pos, pos + bytesLength);
        console.log('无需分包或者最后一包:', tmpBuffer);
        pos += bytesLength;
        bytesLength -= bytesLength;
        that.writeBLEDataCommon(tmpBuffer, deviceId, serviceId, characteristicId,
          function (res) {
            that.output(`最后包发送成功 ${tmpBuffer}`)
          },
          function (res) {
            if (res.errCode == '10006') {
              that.closeConnection(); //清空连接数据
              that.output('当前连接已断开');
            }
            that.output(`发送失败 ${res}`)
          })
      }
    }
  },

  // 配合上面的方法
  writeBLEDataCommon(buffer, deviceId, serviceId, characteristicId) {

    let that = this
    wx.writeBLECharacteristicValue({
      deviceId: deviceId,
      serviceId: serviceId,
      characteristicId: characteristicId,
      value: buffer,
      success: (res) => {
        console.log('发送数据成功:', res)
        this.output('发送数据成功')
        // this.readBleData();
      },
      fail: (err) => {
        console.log('发送数据失败:', err)
        this.output('发送数据失败')
      }
    });
  },


  // WSN 改写的
  writeBLEDataCommon(buffer, deviceId, serviceId, characteristicId, sucFunc, failFunc) {
    wx.writeBLECharacteristicValue({
      deviceId: deviceId,
      serviceId: serviceId,
      characteristicId: characteristicId,
      value: buffer,
      success: sucFunc,
      fail: failFunc,
      success: (res) => {
        console.log('发送数据成功:', res)
        this.output('发送数据成功')
        // this.readBleData();
      },
      fail: (err) => {
        console.log('发送数据失败:', err)
        this.output('发送数据失败')
      }
    });
  },

  // 设置接收监听
  setRecvListener_new(deviceId, serviceId, characteristicId) {
    let that = this
    wx.readBLECharacteristicValue({
      deviceId: deviceId,
      serviceId: serviceId,
      characteristicId: characteristicId,
      state: true,
      success(res) {
        console.log('readBLECharacteristicValue success', res);
        that.output('监听返回数据成功')
        wx.onBLECharacteristicValueChange((res2) => {
          //处理蓝牙返回的数据
          if (characteristicId.toUpperCase() == META_CHAR_UUID) {
            that.handleRecvData_meta(res2.value);
          } else {
            that.handleRecvData_data(res2.value);
          }

        })
      },
      fail(err) {
        console.log('监听读取失败：', err)
        that.output(`监听读取失败： ${err}`)
      }
    })

    // // 监听蓝牙设备连接状态变化
    // // 连接状态的监听无法取消息，用标志位控制避免重复监听
    // if (!this.data.connectStateListening) {
    //   this.data.connectStateListening = true;
    //   wx.onBLEConnectionStateChange(function (res) {
    //     let deviceId = res.deviceId;
    //     const connected = res.connected;
    //     // console.log('蓝牙设备连接状态变化：', deviceId, connected);
    //     if (!connected) {
    //       // 蓝牙设备已断开连接，进行相应处理
    //       that.output('蓝牙设备已断开连接');
    //       that.data.listening = false;
    //     }
    //   });
    // }
  },



  // 移除接收监听
  removeRecvListener() {
    let that = this
    this.output('removeRecvListener...')
    wx.offBLECharacteristicValueChange((res) => {
      console.log('取消蓝牙数据接收');
      that.output('取消监听蓝牙接收数据事件');
    })
    wx.offBLEConnectionStateChange((result) => {
      that.output(`取消监听蓝牙连接事件 ${result}`);
    })
  },

  // 停止蓝牙设备搜索
  stopBluetoothDevicesDiscovery() {
    wx.stopBluetoothDevicesDiscovery()
  },

  // 输出日志
  output(info) {
    const formattedTime = new Date().toISOString();
    info = `${formattedTime}: ${info}`;
    this.data.logInfo.push(info)
    this.setData(this.data)
  },

  // 清空日志
  clearOutput() {
    this.data.logInfo = []
    this.setData(this.data)
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {
    // 接收蓝牙的内容。
    this.truetalkReadMessage();
  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {

  },

    // 回到上一个页面。
    onBack: function () {
      wx.navigateBack({
        delta: 1
      })
      
    },
    // 回到首页
    onHome: function () {
      wx.switchTab({
        url: '../index/index',
      })
    }

});  